﻿using System;
using System.Diagnostics;
using Informant.UI.Credentials;
using Informant.UI.Views;

namespace Informant.UI.ViewModels
{
	public class LogOnViewModel : BindableObject
	{
		#region Fields

		private const String DEFAULT_LOG_ON_FAILURE_MESSAGE = "Authentication failed. Please try again.";
		private Boolean _logOnFailed;
		private Boolean _isLogOnInProgress;
		private String _logOnFailureMessage;
		private String _username;
		private String _password;
		private Boolean _rememberCredentials;

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets a value indicating whether [log on call in progress].
		/// </summary>
		/// <value>
		/// 	<c>true</c> if [log on call in progress]; otherwise, <c>false</c>.
		/// </value>
		public Boolean IsLogOnInProgress
		{
			[DebuggerStepThrough]
			get { return _isLogOnInProgress; }
			set
			{
				_isLogOnInProgress = value;
				PropertyChange("IsLogOnInProgress");
			}
		}
		/// <summary>
		/// Gets or sets the log on failure message.
		/// </summary>
		/// <value>The log on failure message.</value>
		public String LogOnFailureMessage
		{
			[DebuggerStepThrough]
			get { return _logOnFailureMessage; }
			set
			{
				_logOnFailureMessage = value;
				PropertyChange("LogOnFailureMessage");
			}
		}
		/// <summary>
		/// Gets or sets a value indicating whether [log on failed].
		/// </summary>
		/// <value><c>true</c> if [log on failed]; otherwise, <c>false</c>.</value>
		public Boolean LogOnFailed
		{
			[DebuggerStepThrough]
			get { return _logOnFailed; }
			set
			{
				_logOnFailed = value;
				PropertyChange("LogOnFailed");
			}
		}
		/// <summary>
		/// Gets or sets the username.
		/// </summary>
		/// <value>The username.</value>
		public String Username
		{
			[DebuggerStepThrough]
			get { return _username; }
			set
			{
				_username = value;
				PropertyChange("Username");
			}
		}
		/// <summary>
		/// Gets or sets the password.
		/// </summary>
		/// <value>The password.</value>
		public String Password
		{
			[DebuggerStepThrough]
			get { return _password; }
			set
			{
				_password = value;
				PropertyChange("Password");
			}
		}
		/// <summary>
		/// Gets or sets a value indicating whether to remember the credentials when logging in.
		/// </summary>
		/// <value><c>true</c> if the user wants the application to remember the credentials; otherwise, <c>false</c>.</value>
		public Boolean RememberCredentials
		{
			[DebuggerStepThrough]
			get { return _rememberCredentials; }
			set
			{
				if (value == _rememberCredentials)
					return;

				_rememberCredentials = value;
				PropertyChange("RememberCredentials");
			}
		}
		
		#endregion

		#region Commands

		/// <summary>
		/// Command used for logging the user on. Username and Password must be set to enable this command.
		/// </summary>
		/// <value>The log on.</value>
		public DelegateCommand<Object> LogOn { get; set; }
		Boolean CanLogOn(Object obj)
		{
			return !String.IsNullOrEmpty(Username)
				&& !String.IsNullOrEmpty(Password)
				&& !IsLogOnInProgress;
		}
		void LogOnHandler(Object obj)
		{
			IsLogOnInProgress = true;
			ApplicationContext.Instance.LogOn(Username, Password, LogOnHandlerCallback);
		}
		void LogOnHandlerCallback(Boolean succeded, String failureMessage)
		{
			if (succeded)
			{
				if (RememberCredentials)
				{
					CredentialsHelper.SaveCredsToStorage(new IsoCreds(Username, Password));
				}
				else
				{
					CredentialsHelper.RemoveAnySavedCredsFromStorage();
				}
				ChangeStateToLogOnSuccess();
			}
			else
			{
				ChangeStateToLogOnFailure(failureMessage);
			}
			IsLogOnInProgress = false;
		}

		#endregion

		#region Construction
		public LogOnViewModel()
		{
			LogOn = new DelegateCommand<Object>(LogOnHandler, CanLogOn, new String[] { "Username", "Password" });
			IsoCreds creds = CredentialsHelper.LoadCredsFromStorage();
			if (creds != null)
			{
				Username = creds.Username;
				Password = creds.Password;
				RememberCredentials = true;
			}
		}
		#endregion

		#region Private Methods

		/// Sets the necessary properties to display a log on failure.
		/// </summary>
		/// <param name="message">The message.</param>
		private void ChangeStateToLogOnFailure(String message)
		{
			LogOnFailed = true;
			LogOnFailureMessage = !String.IsNullOrEmpty(message) ? message : DEFAULT_LOG_ON_FAILURE_MESSAGE;
		}
		/// <summary>
		/// Sets the necessary properties to display a log on failure.
		/// </summary>
		/// <param name="message">The message.</param>
		private void ChangeStateToLogOnSuccess()
		{
			LogOnFailed = false;
			LogOnFailureMessage = null;
			Controller.Instance.Get<IViewContainer>().Navigate(Controller.Instance.Get<ISmsMessagingView>());
		}

		#endregion
	}
}
